﻿#pragma once
namespace LK
{
	namespace Drawing
	{
		/**@brief 表示一条线段，T表示坐标数据的类型，比如int、float等*/
		template<class T>class Line
		{
		public:
			/**@brief 起点坐标*/
			Point<T> p1;
			/**@brief 终点*/
			Point<T> p2;
			/**@brief 默认构造*/
			Line(){}
			/**@brief 由起点和终点构造*/
			Line(Point<T> const& pStart, Point<T> const& pEnd) :p1(pStart), p2(pEnd){}
			/**@brief 由四个坐标构造*/
			Line(T const& x1, T const& y1, T const& x2, T const& y2) :p1(x1, y1), p2(x2, y2){}
			/**@brief 从其他类型的线段构造*/
			template<class OT>Line(Line<OT>const& ot) : p1(ot.p1), p2(ot.p2){}
			/**@brief 坐标正偏移*/
			inline friend Line operator+(const Line & p1, const Point<T> & p2){ return Line(p1.p1 + p2, p1.p2 + p2); }
			inline Line & operator+=(const Point<T> & p){ return *this = *this + p; }
			inline Line operator + (){ return *this; }
			/**@brief 坐标负偏移*/
			inline friend Line operator-(const Line & p1, const Point<T> & p2){ return Line(p1.p1 - p2, p1.p2 - p2); }
			Line & operator-=(const Point<T> & p){ return *this = *this - p; }
			inline Line operator - (){ return Line(-p1, -p2); }
			/**@brief 坐标乘*/
			inline friend Line operator*(const Line & p, const T & i){ return Line(p.p1*i, p.p2*i); }
			Line & operator*=(const T & i){ return *this = *this * i; }
			/**@brief 坐标除*/
			inline friend Line operator/(const Line & p, const T & i){ return Line(p.p1 / i, p.p2 / i); }
			Line & operator/=(const T & i){ return *this = *this / i; }
			/**@brief 比较*/
			bool operator==(Line const& l)const{ return l.p1 == p1&&p2 == l.p2; }
			bool operator!=(Line const& l)const{ return l.p1 != p1 || p2 != l.p2; }
			/**@brief 获取线段长度的平方*/
			T GetLengthSqr()const{ T t1 = (p2.x - p1.x), t2 = (p2.y - p1.y); return t1*t1 + t2*t2; }
			/**@brief 获取中点坐标*/
			Point<T> GetMidpoint()const{ return (p1+p2)/2; }
		};
		/**@brief 表示一条3D线段，T表示坐标数据的类型，比如int、float等*/
		template<class T>class Line3D
		{
		public:
			/**@brief 起点坐标*/
			Point3D<T> p1;
			/**@brief 终点*/
			Point3D<T> p2;
			/**@brief 默认构造*/
			Line3D(){}
			/**@brief 由起点和终点构造*/
			Line3D(Point3D<T> const& pStart, Point3D<T> const& pEnd) :p1(pStart), p2(pEnd){}
			/**@brief 由四个坐标构造*/
			Line3D(T const& x1, T const& y1, T const& z1, T const& x2, T const& y2, T const& z2) :p1(x1, y1,z1), p2(x2, y2,z2){}
			/**@brief 从其他类型的2D线段构造*/
			template<class OT>Line3D(Line<OT>const& ot) : p1(ot.p1), p2(ot.p2){}
			/**@brief 从其他类型的线段构造*/
			template<class OT>Line3D(Line3D<OT>const& ot) : p1(ot.p1), p2(ot.p2){}
			/**@brief 坐标偏移*/
			inline friend Line3D operator+(const Line3D & p1, const Point3D<T> & p2){ return Line3D(p1.p1 + p2, p1.p2 + p2); }
			inline Line3D & operator+=(const Point3D<T> & p){ return *this = *this + p; }
			inline Line3D operator + (){ return *this; }
			/**@brief 坐标偏移*/
			inline friend Line3D operator-(const Line3D & p1, const Point3D<T> & p2){ return Line3D(p1.p1 - p2, p1.p2 - p2); }
			Line3D & operator-=(const Point3D<T> & p){ return *this = *this - p; }
			inline Line3D operator - (){ return Line3D(-p1, -p2); }
			/**@brief 坐标乘*/
			inline friend Line3D operator*(const Line3D & p, const T & i){ return Line3D(p.p1*i, p.p2*i); }
			Line3D & operator*=(const T & i){ return *this = *this * i; }
			/**@brief 坐标除*/
			inline friend Line3D operator/(const Line3D & p, const T & i){ return Line3D(p.p1 / i, p.p2 / i); }
			Line3D & operator/=(const T & i){ return *this = *this / i; }
			/**@brief 比较*/
			bool operator==(Line3D const& l)const{ return l.p1 == p1&&p2 == l.p2; }
			bool operator!=(Line3D const& l)const{ return l.p1 != p1 || p2 != l.p2; }
			/**@brief 获取线段长度的平方*/
			T GetLengthSqr()const{ T t1 = (p2.x - p1.x), t2 = (p2.y - p1.y),t3=(p2.z-p1.z); return t1*t1 + t2*t2+t3*t3; }
			/**@brief 获取中点坐标*/
			Point<T> GetMidpoint()const{ return (p1 + p2) / 2; }
		};
	}
}
